package org.whale.bha.util;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

import javax.net.ssl.SSLContext;

import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.fluent.Form;
import org.apache.http.client.fluent.Request;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContexts;
import org.whale.bha.bean.ExtendPro;
import org.whale.bha.bean.base.BHABaseRequest;
import org.whale.bha.bean.base.BHABaseResponse;
import org.whale.bha.bean.type.BHAPropertiesEnum;
import org.whale.bha.bean.type.BHAServiceNameEnum;
import org.whale.bha.common.BHACommon;
import org.whale.bha.handler.ResponseHandlerTool;
import org.whale.bha.util.HttpClientUtils.HttpClientException;

/**
 * 易宝调用类
 * @author sshss
 *
 */
public class BHAUtil {
    private static final CloseableHttpClient httpClient;
    
    protected static CloseableHttpClient getHttpClient(){
    	return httpClient;
    }

	static{
		try {
			// SSL context for secure connections can be created either based on
			// system or application specific properties.
			SSLContext sslcontext = SSLContexts.createSystemDefault();

			// Create a registry of custom connection socket factories for supported
			// protocol schemes.
			Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
			    .register("http", PlainConnectionSocketFactory.INSTANCE)
			    .register("https", new SSLConnectionSocketFactory(sslcontext))
			    .build();
			PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
			// Configure total max or per route limits for persistent connections
			// that can be kept in the pool or leased by the connection manager.
			connManager.setMaxTotal(100);
			connManager.setDefaultMaxPerRoute(10);
			
			RequestConfig requestConfig = RequestConfig.custom()
			        .setSocketTimeout(5000)
			        .setConnectTimeout(5000)
			        .setConnectionRequestTimeout(5000)
			        .build();
			httpClient = HttpClients.custom()
			        .setConnectionManager(connManager)
			        .setDefaultRequestConfig(requestConfig)
			        .build();
		} catch (Exception e) {
			throw new HttpClientException(e.getMessage(), e);
		}
	}

	/**
	 * 请求易宝接口
	 * @param servcie 服务名称
	 * @param cls  返回的实体封装
	 * @param req 请求的实体
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 */
	public static <T extends BHABaseResponse> T doBHAPost(BHAServiceNameEnum servcie,final Class<T> resCls, BHABaseRequest req) throws ClientProtocolException, IOException{
		String xml = XMLConverUtil.convertToXML(req); 
		return Request.Post(BHACommon.redirectUrl).bodyForm(Form.form().add("service", servcie.name())
				.add("req",  xml)
				.add("sign", BHACommon.SIGN)
				
				.build()).execute().handleResponse(ResponseHandlerTool.createResponseHandler(resCls));
	}
	
	public static <T extends BHABaseResponse> T doBHAService(BHAServiceNameEnum servcie,final Class<T> resCls, BHABaseRequest req) {
		try {
			String xml = XMLConverUtil.convertToXML(req); 
			HttpPost post = new HttpPost(BHACommon.redirectUrl);
			List<NameValuePair> params = new ArrayList<NameValuePair>();  
			params.add(new BasicNameValuePair("service", servcie.name()));  
			params.add(new BasicNameValuePair("req",  xml));  
			params.add(new BasicNameValuePair("sign", SignUtil.sign(xml, BHACommon.getSignPath(), BHACommon.key)));   
			post.setEntity(new UrlEncodedFormEntity(params,"UTF-8"));  
			return getHttpClient().execute(post, ResponseHandlerTool.createResponseHandler(resCls));
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 设置properties值
	 * @param name
	 * @param value
	 * @param extend
	 */
	public static void setProperties(BHAPropertiesEnum name,String value,List<ExtendPro> extend){
		ExtendPro pro = new ExtendPro();
		pro.setName(name);
		pro.setValue(value);
		extend.add(pro);
	}
	
}
